/*
 * Copyright @ 苏州瑞云信息技术有限公司 All rights reserved.
 */
package work.thread_eg.pool;



import cn.hutool.core.date.DateUtil;

import java.util.concurrent.*;

/**
 * 线程池的使用
 * 
 * 概念
 *      1 线程数比较多的时候, 频繁创建线程和销毁线程需要时间和消耗资源
 *      2 线程池可以实现线程的复用, 线程执行完一个任务之后, 并不销毁, 继续执行其他任务
 *        带来的好处是提高系统响应速度, 降低系统资源消耗
 *      3 线程池中的线程在一定条件下, 长时间没有执行任务也会销毁的
 *
 * ThreadPoolExecutor类
 *      参数
 *          corePoolSize: 核心线程数
 *              线程池中始终存活的线程数
 *              默认情况下, 在创建了线程池后, 线程池中的线程数为0, 当有任务来之后, 就会创建一个线程去执行任务,
 *                  可以使用 prestartAllCoreThreads()或者prestartCoreThread(), 预创建线程
 *              当线程池中的线程数目达到 corePoolSize后, 就会把到达的任务放到缓存队列当中
 *          maximumPoolSize:
 *              线程池中最多能创建多少个线程,  肯定小于等于corePoolSize, 是当任务数多的情况下的一种补救措施,
 *              当 workQueue队列满了, 且已创建的线程数小于 maximumPoolSize, 线程池会创建新的线程来执行任务
 *              对于无界队列, 可忽略该参数, 因为无界队列填不满
 *              如果后期任务数减少, 多余的线程会被销毁(keepAliveTime时间内没有任务执行), 线程数会减少到corePoolSize
 *          keepAliveTime:
 *              线程存活时间
 *              非核心线程的空闲时间超过 keepAliveTime就会被自动终止回收掉 (销毁线程)
 *              也就是当线程池中的线程数大于 corePoolSize, keepAliveTime才生效 (针对线程池的所有线程)
 *              一旦线程数小于corePoolSize , keepAliveTime就失效了, 线程就不会被回收销毁了
 *              调用allowCoreThreadTimeOut(boolean) , 线程数小于corePoolSize时, keepAliveTime参数也会起作用
 *          workQueue:
 *              阻塞队列 BlockingQueue, 用来存储等待执行的任务, 队列里存放的是实现了Runnable接口的对象
 *              while循环里面不断通过getTask()从缓存队列 workQueue 取新的任务来执行
 *              类别
 *                  ArrayBlockingQueue
 *                      有界队列
 *                      需要指定大小 (使用较少)
 *                  LinkedBlockingQueue
 *                      有界队列
 *                      创建时没有指定此队列大小, 则默认为Integer.MAX_VALUE
 *                  SynchronousQueue
 *                      capacity容量是0, 不存储任何元素, 阻塞作用
 *                      不会保存提交的任务, 来了任务就创建线程运行
 *                  DelayQueue
 *                      无界队列
 *                  PriorityBlockingQueue
 *                      一个支持优先级排序的无界阻塞队列。
 *          threadFactory:
 *              线程工厂
 *              ThreadFactory本质是个接口, 默认实现类是 DefaultThreadFactory
 *              newThread()方法用来创建线程, 线程命名, 设置线程的 daemon(守护线程)和优先级等
 *              threadFactory创建的线程名都具有统一的风格: pool-m-thread-n(m为线程池的编号, n为线程池内的线程编号)
 *          handler:
 *              拒绝策略
 *              触发条件
 *                  线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize
 *                  如果还有任务到来就会采取任务拒绝策略
 *                  一般只有自定义的线程池容易触发拒绝策略
 *              策略类型
 *                  AbortPolicy: (默认值) 丢弃任务并抛出RejectedExecutionException异常。
 *                  DiscardPolicy: 也是丢弃任务, 但是不抛出异常。
 *                  DiscardOldestPolicy: 丢弃队列最前面的任务, 然后重新尝试执行任务（重复此过程）
 *                  CallerRunsPolicy: 由调用线程处理该任务
 *      基本方法
 *          execute():      向线程池提交一个任务, 方法没有返回值
 *          submit():       底层调用的execute()方法, 只不过它利用了Future来获取任务执行结果
 *          shutdown():     关闭线程池, 不会接受新的任务, 等剩余任务执行完毕之后关闭线程池
 *          shutdownNow():  关闭线程池, 不会接受新的任务, 尝试打断正在执行的任务
 * 实现原理
 *      线程池状态
 *          RUNNING: 线程池创建之后的状态
 *          SHUTDOWN: 调用了shutdown()方法后的状态, 线程池不能够接受新的任务, 它会等待所有任务执行完毕
 *          STOP: 调用了shutdownNow()方法后的状态, 线程池不能接受新的任务, 并且会去尝试终止正在执行的任务
 *          TERMINATED: 线程池处于SHUTDOWN或STOP状态, 并且所有工作线程已经销毁, 任务缓存队列已经清空或执行结束后,
 *                      线程池被设置为TERMINATED状态
 *      提交任务的处理策略
 *          poolSize 线程池中当前的线程数
 *          1 poolSize < corePoolSize
 *              则每来一个任务, 就会创建一个线程去执行这个任务
 *          2 corePoolSize <= poolSize < maximumPoolSize
 *              则每来一个任务, 会尝试将其添加到任务缓存队列当中, (不创建线程)
 *              若添加成功, 则该任务会等待空闲线程将其取出去执行;
 *              若添加失败（一般来说是任务缓存队列已满）, 则会尝试创建新的线程去执行这个任务
 *          3 poolSize > maximumPoolSize, 则会采取任务拒绝策略进行处理
 *          4 如果线程池中的线程数量大于 corePoolSize时, 如果某线程空闲时间超过keepAliveTime, 线程将被终止
 *
 * 线程池的大小
 *      CPU密集型任务, 就需要尽量压榨 CPU, 参考值可以设为 N(CPU) + 1
 *      IO密集型任务, 参考值可以设置为2*N(CPU)
 *      N(CPU)是服务器CPU的核心数
 *
 * 创建线程池的方法
 *      1 Executors工厂类
 *      2 ThreadPoolExecutor类进行自定义创建
 *
 */
public class ThreadPool {

}
